package model

import (
	"blogcenter/internal/types"
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"
)

type defaultCommentModel struct {
	db *gorm.DB
}

func NewCommentModel(db *gorm.DB) CommentModel {
	return &defaultCommentModel{db: db}
}

// CommentModel 完整接口定义
type CommentModel interface {
	BatchInsertComments(ctx context.Context, indexes []*CommentIndex, contents []*CommentContent) error
	UpdateSubjectCount(ctx context.Context, objectID uint, objectType int, isRoot bool, count int) error
	EnsureSubject(ctx context.Context, objectID uint, objectType int, userID int) error
	// 根据对象查询评论（分页+排序）
	FindByObject(ctx context.Context, objectID int, objectType, page, pageSize int, sort string) ([]*CommentIndex, int64, error)
	// 批量获取评论内容
	FindContents(ctx context.Context, commentIDs []uint) (map[uint]*CommentContent, error)
	// 获取单个评论内容
	FindContent(ctx context.Context, commentID uint) (*CommentContent, error)
	// 获取单个评论索引
	FindIndex(ctx context.Context, commentID uint) (*CommentIndex, error)
	CountRootComments(ctx context.Context, objectType int, objectId uint) (int64, error)
	CountByObject(ctx context.Context, objectType int, objectId uint) (int64, error)
	// 新增分页查询方法
	FindRootComments(
		ctx context.Context,
		objectType int,
		objectId uint,
		page int,
		pageSize int,
		sort string,
	) ([]*CommentIndex, error)

	// 新增转换方法
	ConvertToResponse(
		ctx context.Context,
		indexes []*CommentIndex,
		objectId uint,
	) ([]*types.CommentResponse, error)
	FindReplies(
		ctx context.Context,
		commentId uint,
		objectType int,
		objectId uint,
		page int,
		pageSize int,
	) ([]*CommentIndex, int64, error)
	IncrementLikeCount(ctx context.Context, id uint, count int) error
}

// FindByObject 根据对象查询评论（分页+排序）
func (m *defaultCommentModel) FindByObject(
	ctx context.Context,
	objectID int,
	objectType, page, pageSize int,
	sort string,
) ([]*CommentIndex, int64, error) {
	var indexes []*CommentIndex
	var total int64

	// 计算总数
	err := m.db.WithContext(ctx).
		Model(&CommentIndex{}).
		Where("object_id = ? AND object_type = ?", objectID, objectType).
		Count(&total).Error
	if err != nil {
		return nil, 0, fmt.Errorf("查询评论总数失败: %w", err)
	}

	// 构建查询
	query := m.db.WithContext(ctx).
		Model(&CommentIndex{}).
		Where("object_id = ? AND object_type = ?", objectID, objectType)

	// 设置排序
	switch sort {
	case "hot":
		query = query.Order("like_count DESC, created_at DESC")
	default: // "newest" 或其他默认值
		query = query.Order("created_at DESC")
	}

	// 分页查询
	offset := (page - 1) * pageSize
	err = query.Offset(offset).Limit(pageSize).Find(&indexes).Error
	if err != nil {
		return nil, 0, fmt.Errorf("查询评论列表失败: %w", err)
	}

	return indexes, total, nil
}

// FindContents 批量获取评论内容
func (m *defaultCommentModel) FindContents(
	ctx context.Context,
	commentIDs []uint,
) (map[uint]*CommentContent, error) {
	if len(commentIDs) == 0 {
		return nil, errors.New("commentIDs不能为空")
	}

	var contents []*CommentContent
	err := m.db.WithContext(ctx).
		Where("comment_index_id IN ?", commentIDs).
		Find(&contents).Error
	if err != nil {
		return nil, fmt.Errorf("查询评论内容失败: %w", err)
	}

	// 转换为map
	result := make(map[uint]*CommentContent)
	for _, c := range contents {
		result[c.CommentIndexId] = c
	}

	return result, nil
}

// FindContent 获取单个评论内容
func (m *defaultCommentModel) FindContent(
	ctx context.Context,
	commentID uint,
) (*CommentContent, error) {
	var content CommentContent
	err := m.db.WithContext(ctx).
		Where("comment_index_id = ?", commentID).
		First(&content).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("评论不存在: %w", err)
		}
		return nil, fmt.Errorf("查询评论内容失败: %w", err)
	}

	return &content, nil
}

// FindIndex 获取单个评论索引
func (m *defaultCommentModel) FindIndex(
	ctx context.Context,
	commentID uint,
) (*CommentIndex, error) {
	var index CommentIndex
	err := m.db.WithContext(ctx).
		Where("id = ?", commentID).
		First(&index).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("评论索引不存在: %w", err)
		}
		return nil, fmt.Errorf("查询评论索引失败: %w", err)
	}

	return &index, nil
}

// CountRootComments 统计根评论数量
func (m *defaultCommentModel) CountRootComments(ctx context.Context, objectType int, objectId uint) (int64, error) {
	var subject CommentSubject

	// 查询 comment_subjects 表
	db := m.db.WithContext(ctx).
		Model(&CommentSubject{}).
		Where("object_type = ? AND object_id = ?", objectType, objectId)

	err := db.First(&subject).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return 0, nil // 记录不存在时返回 0
		}
		return 0, fmt.Errorf("查询 comment_subjects 失败: %w", err)
	}

	return int64(subject.RootCount), nil
}

// CountByObject 按对象统计评论数量
func (m *defaultCommentModel) CountByObject(ctx context.Context, objectType int, objectId uint) (int64, error) {
	var subject CommentSubject

	// 查询 comment_subjects 表
	db := m.db.WithContext(ctx).
		Model(&CommentSubject{}).
		Where("object_type = ? AND object_id = ?", objectType, objectId)

	err := db.First(&subject).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return 0, nil // 记录不存在时返回 0
		}
		return 0, fmt.Errorf("查询 comment_subjects 失败: %w", err)
	}

	return int64(subject.Count), nil
}

func (m *defaultCommentModel) FindRootComments(
	ctx context.Context,
	objectType int,
	objectId uint,
	page int,
	pageSize int,
	sort string,
) ([]*CommentIndex, error) {
	var indexes []*CommentIndex
	query := m.db.WithContext(ctx).
		Model(&CommentIndex{}).
		Where("object_type = ? AND object_id = ? AND root = 0",
			objectType,
			objectId)

	switch sort {
	case "hot":
		query = query.Order("like_count DESC")
	default:
		query = query.Order("created_at DESC")
	}

	err := query.Offset((page - 1) * pageSize).
		Limit(pageSize).
		Find(&indexes).Error

	return indexes, err
}

func (m *defaultCommentModel) ConvertToResponse(
	ctx context.Context,
	indexes []*CommentIndex,
	objectId uint,
) ([]*types.CommentResponse, error) {
	var responses []*types.CommentResponse

	for _, idx := range indexes {
		content, err := m.FindContent(ctx, idx.ID)
		if err != nil {
			logx.WithContext(ctx).Errorf("获取评论内容失败: %v", err)
			continue
		}

		// 这里需要获取用户信息，假设有用户服务
		// user, err := getUserInfo(ctx, idx.UserId) // 需要实现
		// if err != nil {
		//     logx.WithContext(ctx).Errorf("获取用户信息失败: %v", err)
		//     continue
		// }

		hasReply, err := m.checkHasReply(ctx, idx.ID)
		if err != nil {
			logx.WithContext(ctx).Errorf("检查回复失败: %v", err)
			continue
		}

		responses = append(responses, &types.CommentResponse{
			ID:         idx.ID,
			Content:    content.Content,
			UserID:     idx.UserId,
			CreateTime: idx.CreatedAt.Format(time.RFC3339),
			LikeCount:  idx.LikeCount,
			UserName:   "",
			Avatar:     "",
			IsReply:    hasReply,
		})
	}

	return responses, nil
}

// 辅助方法
func (m *defaultCommentModel) checkHasReply(ctx context.Context, commentId uint) (int, error) {
	var count int64
	err := m.db.WithContext(ctx).
		Model(&CommentIndex{}).
		Where("root = ?", commentId).
		Count(&count).Error

	return int(count), err
}

func (m *defaultCommentModel) FindReplies(
	ctx context.Context,
	commentId uint,
	objectType int,
	objectId uint,
	page int,
	pageSize int,
) ([]*CommentIndex, int64, error) {
	var replies []*CommentIndex
	var total int64

	// 1. 先获取符合条件的回复总数
	countQuery := m.db.WithContext(ctx).
		Model(&CommentIndex{}).
		Where("root = ? AND object_type = ? AND object_id = ?",
			commentId,
			objectType,
			objectId)

	if err := countQuery.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("查询回复总数失败: %w", err)
	}

	// 2. 获取分页数据
	query := m.db.WithContext(ctx).
		Model(&CommentIndex{}).
		Where("root = ? AND object_type = ? AND object_id = ?",
						commentId,
						objectType,
						objectId).
		Order("created_at DESC") // 默认按时间倒序排列

	if page > 0 && pageSize > 0 {
		offset := (page - 1) * pageSize
		query = query.Offset(offset).Limit(pageSize)
	}

	if err := query.Find(&replies).Error; err != nil {
		return nil, 0, fmt.Errorf("查询回复列表失败: %w", err)
	}

	return replies, total, nil
}
